#include "BuildingNode.h"

#include <osg/Geometry>
#include <osg/Vec4>
#include <osgUtil/Tessellator>
#include <osgUtil/SmoothingVisitor>

#include <QStringList>

BuildingNode::BuildingNode(osg::ref_ptr<osg::Vec3Array> verticies,
    const QString& name,
    const QString& addrCity,
    const QString& addrCountry,
    const QString& addrPostcode,
    const QString& addrStreet,
    const QString& addrSuburb,
    float height)
    : m_name(name),
      m_addrCity(addrCity),
      m_addrCountry(addrCountry),
      m_addrPostcode(addrPostcode),
      m_addrStreet(addrStreet),
      m_addrSuburb(addrSuburb)
{
    setup(verticies, height);
}

BuildingNode::BuildingNode(osg::ref_ptr<osg::Vec3Array> verticies, float height):ToggleNode()
{
    setup(verticies, height);
}

void BuildingNode::setup(osg::ref_ptr<osg::Vec3Array> verticies, float height)
{
    m_color = osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f);

    osg::ref_ptr<osg::Vec3Array> extrudedVertices = new osg::Vec3Array;
    extrudedVertices->insert(extrudedVertices->begin(), verticies->begin(), verticies->end());
    int nVertices = extrudedVertices->size();

    osg::Vec3 offset = osg::Vec3(0.0f, 0.0f, height);
    for(osg::Vec3Array::reverse_iterator itr = verticies->rbegin();
        itr != verticies->rend();
        ++itr)
    {
        extrudedVertices->push_back((*itr) + offset);
    }

    osg::ref_ptr<osg::Geometry> extrusion = new osg::Geometry;
    extrusion->setVertexArray(extrudedVertices.get());
    extrusion->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, 0, nVertices));
    extrusion->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, nVertices, nVertices));

    osgUtil::Tessellator tesselator;
    tesselator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS);
    tesselator.setBoundaryOnly(false);
    tesselator.setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);
    tesselator.setTessellationNormal(osg::Vec3(0.0,0.0,1.0));
    tesselator.retessellatePolygons(*extrusion);

    // proceed after handling the cap polygons
    osg::ref_ptr<osg::DrawElementsUInt> sideIndices = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP);
    for (int i=0; i<nVertices; ++i)
    {
        sideIndices->push_back(i);
        sideIndices->push_back((nVertices-1-i) + nVertices);
    }
    sideIndices->push_back(0);
    sideIndices->push_back(nVertices*2 - 1);
    extrusion->addPrimitiveSet(sideIndices.get());

    // calculate normals
    osgUtil::SmoothingVisitor::smooth(*extrusion, osg::DegreesToRadians(90.0));

    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array();
    colors->push_back(m_color);
    extrusion->setColorArray(colors.get());
    extrusion->setColorBinding(osg::Geometry::BIND_OVERALL);

    this->addDrawable(extrusion);
}

BuildingNode::~BuildingNode()
{

}

QString BuildingNode::getFeatureString()
{
    QString message;
    message.append("name: ").append(m_name).append("\n");
    message.append("address: ").append(m_addrCity).append("\n");
    message.append("country: ").append(m_addrCountry).append("\n");
    message.append("postcode: ").append(m_addrPostcode).append("\n");
    message.append("street: ").append(m_addrStreet).append("\n");
    message.append("suburb: ").append(m_addrSuburb);
    
    return message;
}

